/*
 * ThumbnailCell.java
 *
 * Created on December 18, 2002, 4:04 PM
 */

package fr.umlv.cmis.listview;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.image.BufferedImage;
import java.io.IOException;

import javax.imageio.ImageReadParam;
import javax.imageio.ImageReader;
import javax.imageio.event.IIOReadProgressListener;
import javax.imageio.event.IIOReadUpdateListener;
import javax.swing.BorderFactory;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

import kiyut.swing.shell.image.ImageUtilities;

// TODO: Auto-generated Javadoc
/**
 * The Class CmisThumbnailCell.
 */
public class CmisThumbnailCell extends JComponent implements IIOReadUpdateListener, IIOReadProgressListener {
    
    /** The Constant serialVersionUID. */
	private static final long serialVersionUID = 1L;
	
	/** The IMAG e_ width. */
	private static int IMAGE_WIDTH = 128;
    
    /** The IMAG e_ height. */
    private static int IMAGE_HEIGHT = 128;
    
    /** The label. */
    protected JLabel label;
    
    /** The image pane. */
    protected ImagePane imagePane;
    
    /** The editor. */
    protected JComponent editor;
    
    /** The cell has focus. */
    protected boolean cellHasFocus = false;
    
    /** The editing. */
    protected boolean editing = false;
    
    /** The thumbnail view. */
    protected CmisThumbnailView thumbnailView;
    
    /** The progress. */
    protected float progress = 0;
    
    /**
     * Instantiates a new cmis thumbnail cell.
     *
     * @param thumbnailView the thumbnail view
     */
    public CmisThumbnailCell(CmisThumbnailView thumbnailView) {
        this.thumbnailView = thumbnailView;
        
        int width = 128;
        
        imagePane = new ImagePane();
        imagePane.setPreferredSize(new Dimension(width,128));
        imagePane.setBorder(BorderFactory.createEtchedBorder());
        imagePane.setOpaque(false);
        
        label = new JLabel();
        label.setPreferredSize(new Dimension(width,20));
        label.setHorizontalAlignment(SwingConstants.CENTER);
        label.setVerticalAlignment(SwingConstants.TOP);
        label.setLabelFor(imagePane);
        label.setText("filename");
        label.setOpaque(false);
        
        this.setLayout(new BorderLayout());
        this.add(imagePane, BorderLayout.CENTER);
        this.add(label, BorderLayout.SOUTH);
    }
    
    /* (non-Javadoc)
     * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
     */
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        
        label.setFont(thumbnailView.getFont());
        
        Insets insets = getInsets();
        int x = insets.left;
        int y = insets.top;
        int w = getWidth() - insets.left - insets.right;
        int h = getHeight() - insets.top - insets.bottom;
        
        if (editing) {
            label.setForeground(thumbnailView.getForeground());
            g.setColor(thumbnailView.getBackground());
            g.fillRect(x,y,w,h);
        } else {
            if (cellHasFocus) {
                label.setForeground(thumbnailView.getSelectionForeground());
                g.setColor(thumbnailView.getSelectionBackground());
                g.fillRect(x,y,w,h);
            } else {
                label.setForeground(thumbnailView.getForeground());
                g.setColor(thumbnailView.getBackground());
                g.fillRect(x,y,w,h);
            }
        }
    }
    
    /**
     * Sets the text.
     *
     * @param text the new text
     */
    public void setText(String text) {
        label.setText(text);
    }
    
    /**
     * Gets the text.
     *
     * @return the text
     */
    public String getText() {
        return label.getText();
    }
    
    /**
     * Sets the image.
     *
     * @param image the new image
     */
    public void setImage(BufferedImage image) {
        imagePane.setImage(image);
    }
    
    /**
     * Gets the image.
     *
     * @return the image
     */
    public BufferedImage getImage() {
        return imagePane.getImage();
    }
    
    /**
     * Sets the image rescale.
     *
     * @param width the width
     * @param height the height
     */
    public void setImageRescale(double width, double height) {
        imagePane.setImageRescale(width,height);
    }
    
    /* (non-Javadoc)
     * @see javax.swing.JComponent#setFont(java.awt.Font)
     */
    public void setFont(Font font) {
        setFont(font);
        label.setFont(font);
    }
    
    /**
     * Sets the cell has focus.
     *
     * @param cellHasFocus the new cell has focus
     */
    public void setCellHasFocus(boolean cellHasFocus) {
        this.cellHasFocus = cellHasFocus;
    }
    
    /**
     * Checks if is cell has focus.
     *
     * @return true, if is cell has focus
     */
    public boolean isCellHasFocus() {
        return this.cellHasFocus;
    }
    
    /**
     * Sets the cell editor.
     *
     * @param editor the new cell editor
     */
    public void setCellEditor(JComponent editor) {
        this.editor = editor;
    }
    
    /**
     * Removes the cell editor.
     */
    public void removeCellEditor() {
        this.editor = null;
    }
    
    /**
     * Start cell editing.
     *
     * @return true, if successful
     */
    public boolean startCellEditing() {
        editing = true;
        editor.setPreferredSize(label.getPreferredSize());
        remove(label);
        add(editor, BorderLayout.SOUTH);
        editor.requestFocusInWindow();
        return true;
    }
    
    /**
     * Stop cell editing.
     *
     * @return true, if successful
     */
    public boolean stopCellEditing() {
        editing = false;
        this.remove(editor);
        this.add(label, BorderLayout.SOUTH);
        return true;
    }
    
    /**
     * Read file image.
     *
     * @param reader the reader
     * @param param the param
     * @return the buffered image
     * @throws IOException Signals that an I/O exception has occurred.
     */
    public BufferedImage readFileImage(ImageReader reader, ImageReadParam param) throws IOException {
        int w = reader.getWidth(0);
        int h = reader.getHeight(0);
        Dimension size = imagePane.getPreferredSize();
        Dimension dest = new Dimension((int)size.getWidth()-5,(int)size.getHeight()-5);
        Dimension src = new Dimension(w,h);
        double scale = ImageUtilities.scaleToFit(src,dest);
        imagePane.setImageRescale(scale,scale);
        
        reader.addIIOReadUpdateListener(this);
        reader.addIIOReadProgressListener(this);
        
        BufferedImage bi = reader.read(0,param);
        
        reader.removeIIOReadUpdateListener(this);
        reader.removeIIOReadProgressListener(this);
        
        // to converserve the memory, once the loading done,
        // resize the big image into the smaller version
        BufferedImage smallImg = ImageUtilities.scaleImageToFit(bi,IMAGE_WIDTH,IMAGE_HEIGHT,this);
        w = smallImg.getWidth();
        h = smallImg.getHeight();
        size = imagePane.getPreferredSize();
        dest = new Dimension((int)size.getWidth()-5,(int)size.getHeight()-5);
        src = new Dimension(w,h);
        scale = ImageUtilities.scaleToFit(src,dest);
        setImage(smallImg);
        setImageRescale(scale,scale);
        repaint();
        
        return bi;
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadUpdateListener#imageUpdate(javax.imageio.ImageReader, java.awt.image.BufferedImage, int, int, int, int, int, int, int[])
     */
    public void imageUpdate(ImageReader source, BufferedImage theImage, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) {
        //imagePane.paintImmediately(minX,minY,width,height);
        //repaint();
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadUpdateListener#passComplete(javax.imageio.ImageReader, java.awt.image.BufferedImage)
     */
    public void passComplete(ImageReader source, BufferedImage theImage) {
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadUpdateListener#passStarted(javax.imageio.ImageReader, java.awt.image.BufferedImage, int, int, int, int, int, int, int, int[])
     */
    public void passStarted(ImageReader source, BufferedImage theImage, int pass, int minPass, int maxPass, int minX, int minY, int periodX, int periodY, int[] bands) {
        //imagePane.setImage(theImage);
        if (pass == 0) {
            imagePane.setImage(theImage);
            repaint();
        }
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadUpdateListener#thumbnailPassComplete(javax.imageio.ImageReader, java.awt.image.BufferedImage)
     */
    public void thumbnailPassComplete(ImageReader source, BufferedImage theThumbnail) {
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadUpdateListener#thumbnailPassStarted(javax.imageio.ImageReader, java.awt.image.BufferedImage, int, int, int, int, int, int, int, int[])
     */
    public void thumbnailPassStarted(ImageReader source, BufferedImage theThumbnail, int pass, int minPass, int maxPass, int minX, int minY, int periodX, int periodY, int[] bands) {
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadUpdateListener#thumbnailUpdate(javax.imageio.ImageReader, java.awt.image.BufferedImage, int, int, int, int, int, int, int[])
     */
    public void thumbnailUpdate(ImageReader source, BufferedImage theThumbnail, int minX, int minY, int width, int height, int periodX, int periodY, int[] bands) {
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadProgressListener#imageComplete(javax.imageio.ImageReader)
     */
    public void imageComplete(ImageReader source) {
        
        
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadProgressListener#imageProgress(javax.imageio.ImageReader, float)
     */
    public void imageProgress(ImageReader source, float percentageDone) {
        if ((percentageDone - progress) >= 10) {
            repaint();
            progress = percentageDone;
        }
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadProgressListener#imageStarted(javax.imageio.ImageReader, int)
     */
    public void imageStarted(ImageReader source, int imageIndex) {
        progress = 0;
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadProgressListener#readAborted(javax.imageio.ImageReader)
     */
    public void readAborted(ImageReader source) {
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadProgressListener#sequenceComplete(javax.imageio.ImageReader)
     */
    public void sequenceComplete(ImageReader source) {
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadProgressListener#sequenceStarted(javax.imageio.ImageReader, int)
     */
    public void sequenceStarted(ImageReader source, int minIndex) {
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadProgressListener#thumbnailComplete(javax.imageio.ImageReader)
     */
    public void thumbnailComplete(ImageReader source) {
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadProgressListener#thumbnailProgress(javax.imageio.ImageReader, float)
     */
    public void thumbnailProgress(ImageReader source, float percentageDone) {
    }
    
    /* (non-Javadoc)
     * @see javax.imageio.event.IIOReadProgressListener#thumbnailStarted(javax.imageio.ImageReader, int, int)
     */
    public void thumbnailStarted(ImageReader source, int imageIndex, int thumbnailIndex) {
    }
    
    /**
     * The Class ImagePane.
     */
    private class ImagePane extends JPanel {
        
        /** The Constant serialVersionUID. */
		private static final long serialVersionUID = 1L;

		/** The image. */
        private BufferedImage image;
        
        /** The scale width. */
        private double scaleWidth = 1.0;
        
        /** The scale height. */
        private double scaleHeight = 1.0;
        
        /**
         * Instantiates a new image pane.
         */
        public ImagePane() { }
        
        /**
         * Sets the image.
         *
         * @param image the new image
         */
        public void setImage(BufferedImage image) {
            this.image = image;
        }
        
        /**
         * Sets the image rescale.
         *
         * @param width the width
         * @param height the height
         */
        public void setImageRescale(double width, double height) {
            this.scaleWidth = width;
            this.scaleHeight = height;
        }
        
        /**
         * Gets the image.
         *
         * @return the image
         */
        public BufferedImage getImage() {
            return image;
        }
        
        /* (non-Javadoc)
         * @see javax.swing.JComponent#paintComponent(java.awt.Graphics)
         */
        public void paintComponent(Graphics g) {
            super.paintComponent(g);    // paint background
            
            if (image == null) {
                return;
            }
            
            Graphics2D g2 = (Graphics2D) g;
            
            double w = image.getWidth() *scaleWidth;
            double h = image.getHeight() *scaleHeight;
            
            Dimension dim = getSize();
            double x = 0;
            double y = 0;
            
            if (dim.getWidth() > w) {
                x = (dim.getWidth() - w)/2;
            }
            
            if (dim.getHeight() > h) {
                y = (dim.getHeight() - h)/2;
            }
            
            g2.drawImage(image,(int)x,(int)y,(int)w,(int)h,this);
        }
    }
    
}
